using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace ScriptBox.Services
{
    public class DBCProcessor
    {
        private readonly string _filePath;
        private readonly int _slotSizeMs;
        private readonly List<MessageInfo> _messages = new List<MessageInfo>();
        private readonly List<SlotInfo> _slotInfos = new List<SlotInfo>();

        private class SlotInfo
        {
            public float Load { get; set; }
            public HashSet<int> MessageIds { get; } = new HashSet<int>();
        }
        public enum BalanceMode
        {
            Load,
            Count
        }

        // 在构造函数添加参数
        private readonly BalanceMode _balanceMode;

        private static readonly Regex BoPattern = new Regex(@"^\s*BO_\s+(\d+)\s+(\w+)\s*:\s*(\d+)\s+(\w+)\s*$");
        private static readonly Regex CyclePattern = new Regex(@"^\s*BA_\s+""GenMsgCycleTime""\s+BO_\s+(\d+)\s+(\d+)\s*;\s*$");
        private static readonly Regex StartDelayPattern = new Regex(@"^\s*BA_\s+""GenMsgStartDelayTime""\s+BO_\s+(\d+)\s+(\d+)\s*;\s*$");
        private static readonly Regex FrameFormatDefPattern = new Regex(@"BA_DEF_\s+BO_\s+""VFrameFormat""\s+ENUM\s+(.*?)\s*;");
        private static readonly Regex FrameFormatDefaultPattern = new Regex(@"BA_DEF_DEF_\s+""VFrameFormat""\s+""(\w+)""\s*;");
        private static readonly Regex FrameFormatOverridePattern = new Regex(@"^BA_\s+""VFrameFormat""\s+BO_\s+(\d+)\s+(\d+)\s*;\s*$");

        const int arbitrationBits_can = 46; // 标准CAN仲裁段bit数（除了数据）
        const int arbitrationBits_canfd = 33; // 标准CAN FD仲裁段bit数（除了数据段）
        const int crcBits_l = 17; // 标准CAN FD CRC bit数(dlc<=16)
        const int crcBits_h = 21; // 标准CAN FD CRC bit数(dlc>16)
        const float dataRateRatio_canfd = 4.0f; // 数据段与仲裁段速率比 (2M/500K)

        // 添加静态构造函数
        static DBCProcessor()
        {
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
        }
        public DBCProcessor(string filePath, int slotSizeMs = 5, BalanceMode mode = BalanceMode.Count)
        {
            _filePath = filePath;
            _slotSizeMs = slotSizeMs;
            _balanceMode = mode;
            InitializeSlots();
        }

        private void InitializeSlots()
        {
            int slotCount = _slotSizeMs == 5 ? 20 : 10;
            _slotInfos.Clear();
            for (int i = 0; i < slotCount; i++)
            {
                _slotInfos.Add(new SlotInfo());
            }
        }

        public void ProcessFile(out string outputPath, out string reportPath)
        {
            ParseDBC();
            CalculateOffsets();
            
            outputPath = GenerateOutputPath();
            reportPath = GenerateReportPath();
            
            GenerateDBC(outputPath);
            GenerateReport(reportPath);
        }

        private void ParseDBC()
        {
            var txMessages = new Dictionary<int, (string Name, string Node, int Length)>();
            var cycleTimes = new Dictionary<int, int>();
            var startDelays = new Dictionary<int, int>();
            var frameFormats = new Dictionary<int, string>();
            var nmMessages = new Dictionary<int, bool>();
            var enumValues = new List<string>(); // 新增：存储枚举字符串列表
            string defaultFrameFormatStr = "";

            // 第一次扫描：提取发送报文
            using (var reader = new StreamReader(_filePath, Encoding.GetEncoding("GB2312")))
            {
                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine();
                    if (line?.StartsWith("BO_ ") == true)
                    {
                        var match = BoPattern.Match(line.Trim());
                        if (match.Success)
                        {
                            var msgId = int.Parse(match.Groups[1].Value);
                            var msgName = match.Groups[2].Value;
                            var length = int.Parse(match.Groups[3].Value); // 新增长度解析
                            var node = match.Groups[4].Value;

                            if (node != "Vector__XXX")
                            {
                                // 添加长度到元组
                                txMessages[msgId] = (msgName, node, length);
                            }
                        }
                    }
                    // 新增枚举定义解析
                    else if (line?.TrimStart().StartsWith("BA_DEF_ BO_") == true)
                    {
                        var match = FrameFormatDefPattern.Match(line);
                        if (match.Success)
                        {
                            enumValues = match.Groups[1].Value.Split(',')
                            .Select(x => x.Trim('"'))
                            .ToList();
                        }
                    }
                    // 解析默认值定义
                    else if (line?.TrimStart().StartsWith("BA_DEF_DEF_") == true)
                    {
                        var match = FrameFormatDefaultPattern.Match(line);
                        if (match.Success)
                        {
                            defaultFrameFormatStr = match.Groups[1].Value.Trim('"');
                        }
                    }
                }
            }

            // 第二次扫描：提取周期和延迟时间
            using (var reader = new StreamReader(_filePath, Encoding.GetEncoding("GB2312")))
            {
                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine()?.Trim();
                    if (string.IsNullOrEmpty(line)) continue;

                    if (line.StartsWith("BA_ \"GenMsgCycleTime\""))
                    {
                        var match = CyclePattern.Match(line);
                        if (match.Success)
                        {
                            var msgId = int.Parse(match.Groups[1].Value);
                            var cycle = int.Parse(match.Groups[2].Value);

                            // 添加过滤条件：排除周期时间为0的报文
                            if (cycle > 0)
                            {
                                cycleTimes[msgId] = cycle;
                            }
                        }
                    }
                    else if (line.StartsWith("BA_ \"GenMsgStartDelayTime\""))
                    {
                        var match = StartDelayPattern.Match(line);
                        if (match.Success)
                        {
                            var msgId = int.Parse(match.Groups[1].Value);
                            var delay = int.Parse(match.Groups[2].Value);
                            startDelays[msgId] = delay;
                        }
                    }
                    else if (line?.StartsWith("BA_ \"VFrameFormat\"") == true)
                    {
                        var match = FrameFormatOverridePattern.Match(line);
                        if (match.Success)
                        {
                            var msgId = int.Parse(match.Groups[1].Value);
                            var formatIndex = int.Parse(match.Groups[2].Value);
                            if (formatIndex >= 0 && formatIndex < enumValues.Count)
                            {
                                frameFormats[msgId] = enumValues[formatIndex];
                            }
                        }
                    }
                    else if (line?.StartsWith("BA_ \"NmMessage\"") == true)
                    {
                        var match = Regex.Match(line, @"BO_ (\d+) (\d+)");
                        if (match.Success)
                        {
                            var msgId = int.Parse(match.Groups[1].Value);
                            nmMessages[msgId] = match.Groups[2].Value == "1";
                        }
                    }
                }
            }

            // 修改原来的赋值方式
            _messages.Clear();
            _messages.AddRange(
                txMessages
                    .Where(kv => cycleTimes.ContainsKey(kv.Key) &&
                        (!nmMessages.ContainsKey(kv.Key) || !nmMessages[kv.Key]))
                    .Select(kv => new MessageInfo
                    {
                        Id = kv.Key,
                        Name = kv.Value.Name,
                        Length = kv.Value.Length,
                        FrameFormat = frameFormats.TryGetValue(kv.Key, out var ff) ? ff : defaultFrameFormatStr ,
                        Cycle = cycleTimes.TryGetValue(kv.Key, out var ct) ? ct : (int?)null,
                        ExistingDelay = startDelays.TryGetValue(kv.Key, out var sd) ? sd : (int?)null
                    })
            );
        }

        private void CalculateOffsets()
        {
            var sortedMsgs = _messages
                .Where(m => m.Cycle.HasValue)
                .OrderBy(m => m.Cycle)
                .ThenBy(m => m.Id)
                .ToList();

            foreach (var msg in sortedMsgs)
            {
                var cycle = msg.Cycle.Value;
                var slotCount = _slotInfos.Count;
                float effectiveBits = 0;
                if (_balanceMode == BalanceMode.Load)
                {
                    if (msg.FrameFormat == "StandardCAN_FD" || msg.FrameFormat == "ExtendedCAN_FD") // canfd
                    {
                        int dataBits = msg.Length * 8 + (msg.Length <= 16 ? crcBits_l : crcBits_h);   // 数据段bit数
                        effectiveBits = (msg.FrameFormat == "StandardCAN_FD" ? arbitrationBits_canfd : (arbitrationBits_canfd + 18)) + (dataBits / dataRateRatio_canfd);
                    }
                    else // can
                    {
                        int dataBits = msg.Length * 8;   // 数据段bit数
                        effectiveBits = arbitrationBits_can + dataBits;
                    }
                }
                else
                {
                    effectiveBits = 1;
                }

                int minSlot = 0;

                if (cycle < 100)
                {
                    int requiredSlots = 100 / cycle;
                    int step = cycle / _slotSizeMs;
                    float minLoad = int.MaxValue;

                    for (int slot = 0; slot < slotCount; slot++)
                    {
                        float totalLoad = 0;
                        for (int i = 0; i < requiredSlots; i++)
                        {
                            totalLoad += _slotInfos[(slot + i * step) % slotCount].Load;
                        }

                        if (totalLoad < minLoad)
                        {
                            minLoad = totalLoad;
                            minSlot = slot;
                        }
                    }

                    msg.Offset = minSlot * _slotSizeMs;
                    for (int i = 0; i < requiredSlots; i++)
                    {
                        int slot = (minSlot + i * step) % slotCount;
                        _slotInfos[slot].Load += effectiveBits;
                        _slotInfos[slot].MessageIds.Add(msg.Id);
                    }
                }
                else
                {
                    // 修改为基于bit数的负载查找
                    minSlot = Enumerable.Range(0, slotCount)
                        .Select(i => new { Index = i, Load = _slotInfos[i].Load })
                        .OrderBy(x => x.Load)
                        .First().Index;

                    msg.Offset = minSlot * _slotSizeMs;
                    _slotInfos[minSlot].Load += effectiveBits;
                    _slotInfos[minSlot].MessageIds.Add(msg.Id);
                }
            }
        }

        private void GenerateDBC(string outputPath)
        {
            var offsetMap = _messages
                .Where(m => m.Offset != 0)
                .ToDictionary(m => m.Id, m => m.Offset);

            // 读取所有行到内存中以便二次处理
            var lines = File.ReadAllLines(_filePath, Encoding.GetEncoding("GB2312"));
            var processedIds = new HashSet<int>();
            var newLines = new List<string>();

            // 第一遍：修改现有延迟时间
            foreach (var originalLine in lines)
            {
                var line = originalLine.Trim();
                if (line.StartsWith("BA_ \"GenMsgStartDelayTime\""))
                {
                    var match = StartDelayPattern.Match(line);
                    if (match.Success && int.TryParse(match.Groups[1].Value, out var msgId))
                    {
                        if (offsetMap.TryGetValue(msgId, out var offset))
                        {
                            newLines.Add($"BA_ \"GenMsgStartDelayTime\" BO_ {msgId} {offset};");
                            processedIds.Add(msgId);
                            continue;
                        }
                    }
                }
                newLines.Add(originalLine); // 保持原行不变
            }

            // 第二遍：插入缺失的延迟时间
            for (int i = 0; i < newLines.Count; i++)
            {
                var line = newLines[i].Trim();
                if (line.StartsWith("BA_ \"GenMsgCycleTime\""))
                {
                    var match = CyclePattern.Match(line);
                    if (match.Success && int.TryParse(match.Groups[1].Value, out var msgId))
                    {
                        // 如果存在偏移量且未处理过
                        if (offsetMap.TryGetValue(msgId, out var offset) && !processedIds.Contains(msgId))
                        {
                            // 在周期时间定义后插入延迟时间
                            newLines.Insert(i + 1, $"BA_ \"GenMsgStartDelayTime\" BO_ {msgId} {offset};");
                            processedIds.Add(msgId);
                            i++; // 跳过新增的行
                        }
                    }
                }
            }

            // 写入最终结果
            File.WriteAllLines(outputPath, newLines, Encoding.GetEncoding("GB2312"));
        }


        private void GenerateReport(string reportPath)
        {
            var sortedMsgs = _messages
                .OrderBy(m => m.Cycle)
                .ThenBy(m => m.Id)
                .ToList();

            using (var writer = new StreamWriter(reportPath))
            {
                writer.WriteLine("# DBC报文偏移时间分配报告\n");
                // 修改表格标题行
                writer.WriteLine("| 报文ID | ID(十进制) | 名称 | 类型 | DLC | 周期(ms) | 偏移时间(ms) |");
                writer.WriteLine("|----------|------------|----------|----------|----------|----------|-------------|");

                foreach (var msg in sortedMsgs)
                {
                    // 添加FrameFormat属性输出
                    writer.WriteLine($"| 0x{msg.Id:X} | {msg.Id} | {msg.Name} | {msg.FrameFormat} | {msg.Length} | {msg.Cycle} | {msg.Offset} |");
                }

                // 新增时间槽负载表格
                writer.WriteLine("\n## 时间槽负载分配");
                if (_balanceMode == BalanceMode.Load)
                {
                    writer.WriteLine("| 槽序号 | 起始时间(ms) | 负载(bits) | 报文数量 | 报文ID列表 |");
                    writer.WriteLine("|--------|--------------|------------|----------|------------|");
                }
                else
                {
                    writer.WriteLine("| 槽序号 | 起始时间(ms) | 报文数量 | 报文ID列表 |");
                    writer.WriteLine("|--------|-------------|----------|------------|");
                }
                // 修改时间槽表格输出部分
                    for (int i = 0; i < _slotInfos.Count; i++)
                    {
                        var slot = _slotInfos[i];
                        // 将ID转换为十六进制，添加0x前缀
                        var hexIds = slot.MessageIds.Select(id => $"0x{id:X}");
                        if (_balanceMode == BalanceMode.Load)
                        {
                            writer.WriteLine($"| {i} | {i * _slotSizeMs} | {slot.Load:F2} | {slot.MessageIds.Count} | {string.Join(", ", hexIds)} |");
                        }
                        else
                        {
                            writer.WriteLine($"| {i} | {i * _slotSizeMs} | {slot.MessageIds.Count} | {string.Join(", ", hexIds)} |");
                        }
                    }
            }
        }

        private string GenerateOutputPath()
        {
            string slotSuffix = _slotSizeMs == 10 ? "_10ms" : "";
            return Path.Combine(
                Path.GetDirectoryName(_filePath),
                $"{Path.GetFileNameWithoutExtension(_filePath)}{slotSuffix}_modified.dbc"
            );
        }

        private string GenerateReportPath()
        {
            return Path.Combine(
                Path.GetDirectoryName(_filePath),
                $"{Path.GetFileNameWithoutExtension(_filePath)}_report.md"
            );
        }

        private class MessageInfo
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public int Length { get; set; }
            public string FrameFormat { get; set; }
            public int? Cycle { get; set; }
            public int? ExistingDelay { get; set; }
            public int Offset { get; set; }
        }
    }
}